package net.wangds.jpa.comp;

import net.wangds.common.base.module.Holder;
import net.wangds.data.WithId;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.mongodb.repository.MongoRepository;

import java.util.function.Function;

/**
 * .
 * <p></p>
 *
 * @author 王东石 2020/5/15 21:05.
 */
public class MongoComp {

    /**
     * 获得无法通过非id字段唯一确定记录的查找方法.
     * @param <T> 类型.
     * @return 总是返回null.
     */
    protected <T> Function<T, T> fetchCantFindNotById(){
        return (t)->null;
    }

    /**
     * 保存.
     * @param entity 要保存的实体.
     * @param repo 数据操作Repo对象.
     * @param findNotById 不根据id查找对象的方法.
     * @param <T> 对象类型.
     */
    protected <T extends WithId<String>, R extends MongoRepository<T, String>> T save(T entity, R repo, Function<T, T> findNotById){
        if(entity==null){
            return null;
        }

        Holder<T> h = Holder.of(null);

        String id = entity.getId();
        if(StringUtils.isNotBlank(id)) {
            if (repo != null) {
                h.target = repo.findById(id).orElseGet(() -> {
                    if (findNotById != null) {
                        return findNotById.apply(entity);
                    }
                    return null;
                });
            } else {
                if (findNotById != null) {
                    h.target = findNotById.apply(entity);
                }
            }
        }else{
            if (findNotById != null) {
                h.target = findNotById.apply(entity);
            }
        }

        if(h.target==null){
            return repo.save(entity);
        }else{
            id = h.target.getId();
            BeanUtils.copyProperties(entity, h.target);
            h.target.setId(id);
            return repo.save(h.target);
        }
    }

    /**
     * 保存.
     * @param entity 要保存的实体.
     * @param repo 数据操作Repo对象.
     * @param <T> 对象类型.
     */
    protected <T extends WithId<String>, R extends MongoRepository<T, String>> T save(T entity, R repo){
        return save(entity, repo, fetchCantFindNotById());
    }

}
